package com.lrd.snapshotorder.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lrd.snapshotorder.config.redis.RedisKeyConstants;
import com.lrd.snapshotorder.config.redis.RedissonClientService;
import com.lrd.snapshotorder.entity.OrderTask;
import com.lrd.snapshotorder.mapper.OrderTaskMapper;
import com.lrd.snapshotorder.mapper.SnapshotOrderMapper;
import com.lrd.snapshotorder.protocol.ResultData;
import com.lrd.snapshotorder.protocol.dto.order.OrderTaskCreateDto;
import com.lrd.snapshotorder.protocol.dto.order.OrderTaskListDto;
import com.lrd.snapshotorder.protocol.dto.order.OrderTaskQueryDto;
import com.lrd.snapshotorder.service.OrderTaskService;
import com.lrd.snapshotorder.service.rule.IRule;
import com.lrd.snapshotorder.service.rule.IRuleService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.concurrent.ThreadPoolExecutor;

import static java.lang.Thread.sleep;

@Service
@Slf4j
public class OrderTaskServiceImpl implements OrderTaskService {

    @Autowired
    private OrderTaskMapper orderTaskMapper;
    @Autowired
    private RedissonClientService redisService;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private IRuleService ruleService;
    @Autowired
    @Qualifier(value = "orderVerifyThreadPool")
    private ThreadPoolExecutor orderVerifyThreadPool;
    @Autowired
    private SnapshotOrderMapper snapshotOrderMapper;

    @Override
    @Transactional
    public ResultData<Boolean> createOrderTask(OrderTaskCreateDto orderTaskCreateDto) {
        Integer batchNumber = redisService.getBatchNumberByDate(orderTaskCreateDto.getPostTime());
        orderTaskCreateDto.setBatchNumber(batchNumber);
        IRule rule = this.ruleService.findRule(orderTaskCreateDto.getScene());
        rule.verify(orderTaskCreateDto);
        boolean exist = orderTaskMapper.selectBatchNumberIsExist(batchNumber);
        if (exist) {
            return ResultData.error("次批次号已存在" + batchNumber);
        }
        OrderTask orderTask = BeanUtil.toBean(orderTaskCreateDto, OrderTask.class);
        orderTask.setStatus(0);
        orderTaskMapper.insert(orderTask);
        RAtomicLong atomicLong = redissonClient.getAtomicLong(RedisKeyConstants.getOrderBatchNumberSize(batchNumber.toString()));
        atomicLong.set(orderTask.getBatchSize());
        rule.createOrder(orderTaskCreateDto);
        orderVerifyThreadPool.execute(() -> {
            orderTaskStatusVerify(orderTask);
        });
        return ResultData.success(true);
    }

    @Override
    public ResultData<List<OrderTaskListDto>> orderTaskList(OrderTaskQueryDto queryDto) {
        ResultData<List<OrderTaskListDto>> resultData = new ResultData<>();
        resultData.setCode(0);
        Page<OrderTask> orderTaskPage = orderTaskMapper.orderTaskList(queryDto);
        if (CollUtil.isNotEmpty(orderTaskPage.getRecords())) {
            List<OrderTaskListDto> orderTaskListDtos = BeanUtil.copyToList(orderTaskPage.getRecords(), OrderTaskListDto.class);
            resultData.setData(orderTaskListDtos);
            resultData.setTotal(orderTaskPage.getTotal());
            return resultData;
        }
        resultData.setMessage("订单任务列表为空");
        return resultData;
    }

    @Override
    public void orderTaskStatusVerify(OrderTask orderTask) {

        new Thread(new Runnable() {
            boolean finish = false;
            int times = 1;

            @Override
            public void run() {
                while (!finish) {
                    int total = snapshotOrderMapper.selectCountByBatchNumber(orderTask);
                    if (orderTask.getBatchSize() == total) {
                        orderTask.setStatus(1);
                        orderTaskMapper.updateById(orderTask);
                        finish = true;
                    } else if (times == 30) {
                        orderTask.setStatus(2);
                        orderTaskMapper.updateById(orderTask);
                        finish = true;
                    } else {
                        times++;
                        try {
                            sleep(10000);
                        } catch (InterruptedException e) {
                            log.error("" + e);
                        }
                    }
                }
            }
        }).start();
    }
}
